package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.excel.poi.ExcelBoot;
import com.excel.poi.function.ExportFunction;
import com.qinglei.recoup.common.tenant.TenantContextHolder;
import com.qinglei.recoup.common.utils.DateUtil;
import com.qinglei.recoup.common.utils.RecoupUtil;
import com.qinglei.recoup.system.dao.NurseStatisticsMapper;
import com.qinglei.recoup.system.domain.EventLogData4NurseBO;
import com.qinglei.recoup.system.domain.EventStatisticsBO;
import com.qinglei.recoup.system.domain.NurseStatistics;
import com.qinglei.recoup.system.domain.TourStatisticsBO;
import com.qinglei.recoup.system.pojo.NurseWorkSearchParam;
import com.qinglei.recoup.system.pojo.NurseWorkVO;
import com.qinglei.recoup.system.service.EventLogService;
import com.qinglei.recoup.system.service.EventProcService;
import com.qinglei.recoup.system.service.NurseOnlineService;
import com.qinglei.recoup.system.service.NurseStatisticsService;
import com.qinglei.recoup.system.service.TourLogService;
import com.qinglei.recoup.system.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author syp
 */
@Service
public class NurseStatisticsServiceImpl extends ServiceImpl<NurseStatisticsMapper, NurseStatistics> implements NurseStatisticsService {
    @Resource
    private NurseOnlineService nurseOnlineService;
    @Resource
    private TourLogService tourLogService;
    @Resource
    private EventProcService eventProcService;
    @Resource
    private EventLogService eventLogService;
    @Resource
    private UserService userService;

    @Override
    public NurseStatistics getStatisticsByDay(Long userId, LocalDate day) {
        Integer onlineTime = nurseOnlineService.getOnlineTimeByDay(userId, day);
        TourStatisticsBO tourData = tourLogService.getTourDataByDay(userId, day);
        EventStatisticsBO eventProcData = eventProcService.getEventProcDataByDay(userId, day);
        EventLogData4NurseBO eventLogData = eventLogService.getNurseStatisticsDataByDay(userId, day);
        NurseStatistics nurseStatistics = new NurseStatistics();
        nurseStatistics.setStatisticsDate(day);
        if (onlineTime != 0) {
            nurseStatistics.setWorkTime(onlineTime);
            nurseStatistics.setUserId(userId);
        }
        if (tourData != null) {
            nurseStatistics.setTourTotalTimes(tourData.getTourTotalTimes());
            nurseStatistics.setTourFinishTimes(tourData.getTourFinishTimes());
            nurseStatistics.setTourUseTime(tourData.getTourUseTime());
            nurseStatistics.setUserId(userId);
        }
        if (eventProcData != null) {
            nurseStatistics.setEventTakeTimes(eventProcData.getEventTakeTimes());
            nurseStatistics.setEventWaitTime(eventProcData.getEventWaitTime());
            nurseStatistics.setEventFinishTimes(eventProcData.getEventFinishTimes());
            nurseStatistics.setEventProcTime(eventProcData.getEventProcTime());
            nurseStatistics.setUserId(userId);
        }
        if (eventLogData != null) {
            nurseStatistics.setMissedEventTimes(eventLogData.getMissedEventNum());
        }
        return nurseStatistics;
    }

    /**
     * 获取历史数据（合计）
     *
     * @param userId
     * @param startData 开始日期
     * @param endDate   结束日期（包括）
     * @return
     */
    @Override
    public NurseStatistics getStatisticsHistory(Long userId, LocalDate startData, LocalDate endDate) {
        List<NurseStatistics> nurseStatistics = this.baseMapper.selectList(Wrappers.<NurseStatistics>lambdaQuery()
                .eq(NurseStatistics::getUserId, userId)
                .between(NurseStatistics::getStatisticsDate, startData, endDate));
        if (CollectionUtils.isNotEmpty(nurseStatistics)) {
            NurseStatistics nurseStatisticsDTO = new NurseStatistics();
            nurseStatisticsDTO.setWorkTime(0);
            nurseStatisticsDTO.setTourTotalTimes(0);
            nurseStatisticsDTO.setTourFinishTimes(0);
            nurseStatisticsDTO.setTourUseTime(0);
            nurseStatisticsDTO.setEventTakeTimes(0);
            nurseStatisticsDTO.setEventWaitTime(0);
            nurseStatisticsDTO.setEventFinishTimes(0);
            nurseStatisticsDTO.setEventProcTime(0);
            nurseStatisticsDTO.setMissedEventTimes(0);
            for (NurseStatistics nurseStatistic : nurseStatistics) {
                nurseStatisticsDTO.setWorkTime(nurseStatisticsDTO.getWorkTime() + nurseStatistic.getWorkTime());
                nurseStatisticsDTO.setTourTotalTimes(nurseStatisticsDTO.getTourTotalTimes() + nurseStatistic.getTourTotalTimes());
                nurseStatisticsDTO.setTourFinishTimes(nurseStatisticsDTO.getTourFinishTimes() + nurseStatistic.getTourFinishTimes());
                nurseStatisticsDTO.setTourUseTime(nurseStatisticsDTO.getTourUseTime() + nurseStatistic.getTourUseTime());
                nurseStatisticsDTO.setEventTakeTimes(nurseStatisticsDTO.getEventTakeTimes() + nurseStatistic.getEventTakeTimes());
                nurseStatisticsDTO.setEventWaitTime(nurseStatisticsDTO.getEventWaitTime() + nurseStatistic.getEventWaitTime());
                nurseStatisticsDTO.setEventFinishTimes(nurseStatisticsDTO.getEventFinishTimes() + nurseStatistic.getEventFinishTimes());
                nurseStatisticsDTO.setEventProcTime(nurseStatisticsDTO.getEventProcTime() + nurseStatistic.getEventProcTime());
                nurseStatisticsDTO.setMissedEventTimes(nurseStatisticsDTO.getMissedEventTimes() + nurseStatistic.getMissedEventTimes());
            }
            return nurseStatisticsDTO;
        }
        return null;
    }

    @Override
    public IPage<NurseWorkVO> searchNurseWorkPage(NurseWorkSearchParam searchParam) {
        Integer tenantId = TenantContextHolder.getTenantId();
        //分页查询护工
        IPage<NurseWorkVO> nurseWorkVOIPage = userService.pageNurse(searchParam, tenantId);
        if (nurseWorkVOIPage == null || CollectionUtils.isEmpty(nurseWorkVOIPage.getRecords())) {
            return nurseWorkVOIPage;
        }
        List<NurseWorkVO> records = nurseWorkVOIPage.getRecords();
        Integer type = searchParam.getType();
        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.minusDays(1);
        LocalDate startDay = null;
        if (type == 2) {
            startDay = yesterday;
        } else if (type == 3) {
            startDay = today.minusDays(7);
        } else if (type == 4) {
            startDay = today.minusDays(30);
        }
        for (NurseWorkVO nwv : records) {
            Long userId = nwv.getUserId();
            NurseStatistics nurseStatistics;
            if (type == 1) {
                nurseStatistics = this.getStatisticsByDay(userId, today);
            } else {
                nurseStatistics = this.getStatisticsHistory(userId, startDay, yesterday);
            }
            if (nurseStatistics == null) {
                continue;
            }
            //查询在线时长
            if (nurseStatistics.getWorkTime() != null) {
                nwv.setOnlineTime(DateUtil.formatHourMinute(nurseStatistics.getWorkTime()));
            }
            // 查询巡查次数
            if (nurseStatistics.getTourTotalTimes() != null) {
                // 巡查总次数
                nwv.setTourTotalCnt(nurseStatistics.getTourTotalTimes() + "次");
                // 巡查完成次数
                nwv.setTourSucceedCnt(nurseStatistics.getTourFinishTimes().toString());
                int useSeconds = Math.round(nurseStatistics.getTourUseTime() / (float) nurseStatistics.getTourFinishTimes());
                // 巡视平均用时
                nwv.setTourSpendTime(DateUtil.formatHourMinuteSecond(useSeconds));
            }

            if (nurseStatistics.getEventTakeTimes() != null) {
                nwv.setEventProcCnt(nurseStatistics.getEventTakeTimes().toString());
                int useSeconds = Math.round(nurseStatistics.getEventWaitTime() / (float) nurseStatistics.getEventTakeTimes());
                nwv.setEventWaitTime(DateUtil.formatHourMinuteSecond(useSeconds));
                useSeconds = Math.round(nurseStatistics.getEventProcTime() / (float) nurseStatistics.getEventFinishTimes());
                nwv.setEventProcTime(DateUtil.formatHourMinute(useSeconds));
            }
            // 漏掉异常次数
            if (nurseStatistics.getMissedEventTimes() != null && nurseStatistics.getMissedEventTimes() != 0) {
                nwv.setMissAbnormalCnt(String.valueOf(nurseStatistics.getMissedEventTimes()));
            }
        }
        return nurseWorkVOIPage;
    }

    @Override
    public void exportNurseWork(HttpServletResponse httpServletResponse, NurseWorkSearchParam param) {
        String fileName;
        // 设置起止时间条件
        Integer type = param.getType();
        LocalDate startDate = null;
        LocalDate endDate = LocalDate.now();
        if (type == 2) {
            endDate = endDate.minusDays(1);
        } else if (type == 3) {
            endDate = endDate.minusDays(1);
            startDate = endDate.minusDays(6);
        } else if (type == 4) {
            endDate = endDate.minusDays(1);
            startDate = endDate.minusDays(29);
        }
        if (startDate == null) {
            fileName = "工效分析_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        } else {
            fileName = "工效分析_" + startDate.format(DateTimeFormatter.ISO_LOCAL_DATE)
                    + "_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        }
        ExcelBoot.ExportBuilder(httpServletResponse, fileName, NurseWorkVO.class).exportResponse(param,
                new ExportFunction<NurseWorkSearchParam, NurseWorkVO>() {
                    /**
                     * @param queryParam 查询条件对象
                     * @param pageNum    当前页数,从1开始
                     * @param pageSize   每页条数,默认3000
                     * @return
                     */
                    @Override
                    public List<NurseWorkVO> pageQuery(NurseWorkSearchParam queryParam, int pageNum, int pageSize) {
                        //分页查询操作
                        queryParam.setPageNum((long) pageNum);
                        queryParam.setPageSize((long) pageSize);
                        IPage<NurseWorkVO> nurseWork = searchNurseWorkPage(queryParam);

                        return nurseWork.getRecords();
                    }

                    /**
                     * 将查询出来的每条数据进行转换
                     *
                     * @param o
                     */
                    @Override
                    public NurseWorkVO convert(NurseWorkVO o) {
                        //转换操作
                        return o;
                    }
                });
    }
}
